/**
 * 
 */
package org.tote.controller;

import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.tote.command.ControllerCommand;
import org.tote.command.LoggedUsersCommand;
import org.tote.command.UserCommand;
import org.tote.command.UserCommandLight;
import org.tote.command.UserListCommand;
import org.tote.model.User;
import org.tote.service.user.UserService;
import org.tote.util.Constant;

@Controller
@RequestMapping("/admin/user")
public class UserManagementController implements BaseController {

	private static final Logger LOGGER = LoggerFactory.getLogger(UserManagementController.class);

	private static final String USER_COMMAND = "userCommand";
	private static final String USER_LIST_COMMAND = "userListCommand";
	private static final String USER_MAX_PAGE = "userMaxPage";

	private static final String EDIT_USER_VIEW = "editUser";
	private static final String USER_LIST_VIEW = "adminUserList";
	private static final String CREATION_VIEW = "createUser";

	private static final String LOGGED_USERS_VIEW = "loggedUsers";
	private static final String LOGGED_USERS_COMMAND = "loggedUsersCommand";

	public static final int USERS_PER_PAGE = 20;

	@Autowired
	private UserService userService;

	@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
	public String initEditUserForm(@PathVariable("id") Long id, Map<String, Object> model) {
		User user = userService.getUserById(id);
		user.setPassword(null);
		model.put(USER_COMMAND, new UserCommand(user));

		return EDIT_USER_VIEW;
	}

	@RequestMapping(value = "/edit/*", method = RequestMethod.POST)
	public String saveUserOnEdit(Map<String, Object> model,
			@ModelAttribute @Valid UserCommand userCommand, BindingResult bindingResult) {
		if (userCommand.getName() == null) {
			return EDIT_USER_VIEW;
		}

		if (!Constant.matchPassword(userCommand.getPassword())) {
			model.put(ALERT_ERROR_MESSAGE, Constant.PASSWORD_ERROR);
			return EDIT_USER_VIEW;
		}

		userService.modifyUserModyfiable(userCommand.getId(), userCommand.getEnabled(),
				userCommand.getName(), userCommand.getPassword());

		//User user = userCommand.getAsUser();
		//		List<Long> groupIdList = new ArrayList<Long>();
		//		for (Group group : user.getGroups()) {
		//			groupIdList.add(group.getId());
		//		}
		//		userService.setUserGroups(user, groupIdList);

		return ("redirect:/admin/user/edit/" + userCommand.getId());
	}

	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String initUserListForm(Map<String, Object> map) {
		return this.initUserListPageForm(0, "", map);
	}

	@RequestMapping(value = "/list/page/{page}/", method = RequestMethod.GET)
	public String initUserListFilteredPageForm(@PathVariable int page, Map<String, Object> map) {
		return this.initUserListPageForm(page, "", map);
	}

	@RequestMapping(value = "/list/page/{page}/{searchFilter}", method = RequestMethod.GET)
	public String initUserListPageForm(@PathVariable int page, @PathVariable String searchFilter,
			Map<String, Object> map) {
		LOGGER.info("Loading users list.");

		List<User> userList = userService.getFilteredUsersPage(page, USERS_PER_PAGE, searchFilter);
		boolean more = false;
		if (userList.size() > USERS_PER_PAGE) {
			more = true;
			userList.subList(USERS_PER_PAGE, userList.size()).clear();
		}
		map.put(USER_LIST_COMMAND, new UserListCommand(userList, page, more, searchFilter));
		map.put(USER_MAX_PAGE, userService.getFilteredUsersMaxPage(USERS_PER_PAGE, searchFilter));

		LOGGER.info("User list loaded successfully.");

		return USER_LIST_VIEW;
	}

	@RequestMapping(method = RequestMethod.GET)
	public String viewUserAdministration() {
		return "redirect:/admin/user/list/";
	}

	@RequestMapping(value = "/ban/{id}", method = RequestMethod.GET)
	public String disableUser(@PathVariable("id") Long id) {

		userService.disableUserById(id);
		return "redirect:/admin/user/list/";
	}

	@RequestMapping(value = "/unban/{id}", method = RequestMethod.GET)
	public String enableUser(@PathVariable("id") Long id) {
		userService.enableUserById(id);
		return "redirect:/admin/user/list/";
	}

	@RequestMapping(method = RequestMethod.GET, value = "/create")
	public String loadRegistrationFrom(Map<String, Object> model) {
		model.put(USER_COMMAND, new UserCommand());

		return CREATION_VIEW;
	}

	@RequestMapping(method = RequestMethod.GET, value = "/duplicate/{id}")
	public String loadRegistrationFrom(Map<String, Object> model, @PathVariable("id") Long id) {
		model.put("fromId", id);
		model.put(USER_COMMAND, new UserCommand());

		return CREATION_VIEW;
	}

	@RequestMapping(method = RequestMethod.POST, value = "/create")
	public String registerUser(@ModelAttribute @Valid UserCommand userCommand,
			BindingResult bindingResult, Map<String, Object> model) {
		ControllerCommand controllerCommand = new ControllerCommand();
		Long fromId = userCommand.getFromUserId();
		try {
			if (bindingResult.hasErrors())
				throw new Exception(bindingResult.getFieldError().toString());

			if (!Constant.matchPassword(userCommand.getPassword())) {
				throw new Exception(Constant.PASSWORD_ERROR);
			}

			User user = userCommand.getAsUser();
			if (fromId != null) {
				// duplicate user
				//User fromUser = userService.getUserAndGroupById(fromId);
				//user.setGroups(fromUser.getGroups());
			}
			// create user
			userService.adminCreateUser(user);
			controllerCommand.setSuccessMessage(ControllerCommand.SUCCESS + " User <strong>'"
					+ user.getName() + "'</strong> successfully created");
			controllerCommand.putToModel(model);
			return initUserListForm(model);
		} catch (Exception e) {
			LOGGER.error("Can't create user", e);
			if (fromId != null) {
				model.put("fromId", fromId);
			}
			model.put(USER_COMMAND, userCommand);
			controllerCommand.setErrorMessage(ControllerCommand.ERROR + " Can't create user: "
					+ e.getMessage());
			controllerCommand.putToModel(model);
			return CREATION_VIEW;
		}

	}

	@RequestMapping(value = "/list/logged", method = RequestMethod.GET)
	public String initLoggedUsersPageForm(Map<String, Object> map) {
		return initLoggedUsersPageForm(0, map);
	}

	@RequestMapping(value = "/list/logged/page/{page}", method = RequestMethod.GET)
	public String initLoggedUsersPageForm(@PathVariable int page, Map<String, Object> map) {
		LOGGER.info("Loading logged users list.");

		List<UserCommandLight> loggedUsers = userService.getLoggedUsers();
		int maxUsers = loggedUsers.size();
		boolean more = false;
		if (loggedUsers.size() > USERS_PER_PAGE) {
			loggedUsers.subList(0, USERS_PER_PAGE * page).clear();
			if (loggedUsers.size() > USERS_PER_PAGE) {
				loggedUsers.subList(USERS_PER_PAGE, loggedUsers.size()).clear();
				more = true;
			}
		}

		map.put(LOGGED_USERS_COMMAND, new LoggedUsersCommand(loggedUsers, page, more));
		map.put(USER_MAX_PAGE, maxUsers / USERS_PER_PAGE);

		LOGGER.info("Logged user list loaded successfully.");

		return LOGGED_USERS_VIEW;
	}

	@RequestMapping(value = "/disconnect/{id}")
	public String disconnectUser(@PathVariable("id") Long id) {
		userService.logoutUser(id);
		return "redirect:/admin/user/list/logged";
	}

	@RequestMapping(value = "/disconnectAll")
	public String disconnectAllUsers() {
		userService.logoutAllUsers();
		return "redirect:/admin/user/list/logged";
	}
}
